package com.xjl.remotelink.server;

import com.xjl.remotelink.BaseThread;
import com.xjl.remotelink.LinkLog;
import com.xujl.task.Emitter;
import com.xujl.task.RxExecutor;
import com.xujl.task.Task;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerThread extends BaseThread {
    private static final String TAG = "ServerThread";
    private int linkPort;
    private ServerCallback mCallback;

    public ServerThread (int linkPort, ServerCallback callback) {
        this.linkPort = linkPort;
        mCallback = callback;
    }

    @Override
    public void run () {
        super.run();
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(linkPort);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        while (!isExit()) {
            // receive request from client
            try {
                final Socket client = serverSocket.accept();
                LinkLog.d(TAG, "=============== accept ==================");
                RxExecutor.getInstance().executeTask(new Task<Object>() {
                    @Override
                    public void run (Emitter<Object> emitter) throws Exception {
                        super.run(emitter);
                        responseClient(client);
                    }

                    @Override
                    public void onError (Exception e) {
                        super.onError(e);
                        mCallback.onException(e);
                    }
                });
            } catch (IOException e) {
                e.printStackTrace();
                mCallback.onException(e);
            }
        }
        try {
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
            if (mCallback != null) {
                mCallback.onException(e);
            }
        }
    }

    private void responseClient (Socket client) throws IOException {
        //receive message
        BufferedReader in = new BufferedReader(
                new InputStreamReader(client.getInputStream()));
        String receiveStr = in.readLine();

        //send message
        PrintWriter out = new PrintWriter(
                new BufferedWriter(
                        new OutputStreamWriter(
                                client.getOutputStream())), true);

        LinkLog.d(TAG, "message from client: " + receiveStr);
        mCallback.setMessageWatcher(new MessageWatcher() {
            @Override
            public void sendResult (String data) {
                RxExecutor.getInstance().executeTask(new Task<Object>() {
                    @Override
                    public void run (Emitter<Object> emitter) throws Exception {
                        super.run(emitter);
                        out.println(data);
                        closeStream(in, out, client);
                    }
                });
            }
        });
        RxExecutor.getInstance().executeUiTask(new Task() {
            @Override
            public void onlyRunUiTask () {
                super.onlyRunUiTask();
                mCallback.onReceiveData(receiveStr);
            }
        });
    }

    private void closeStream (BufferedReader in, PrintWriter out, Socket client) throws IOException {
        LinkLog.d(TAG, "send Message: response");
        out.close();
        in.close();
        client.close();
    }
}
